//! 语法树
//!

/// 节点元信息
#[derive(Debug)]
pub struct Node {
    /// 所在行数
    pub line: usize,
    /// 源代码字符串
    pub code: String,
    /// 语法节点类型
    pub node_type: NodeType,
}

impl Default for Node {
    fn default() -> Self {
        Node {
            line: 0,
            code: "".to_string(),
            node_type: NodeType::Unknown,
        }
    }
}

impl Node {
    /// 配置 line, node, code三项
    pub fn new<S: ToString>(code: S, node_type: NodeType) -> Self {
        Node {
            code: code.to_string(),
            node_type,
            ..Self::default()
        }
    }

    pub fn line(mut self, line: usize) -> Self {
        self.line = line;
        self
    }
}

/// 代码节点
#[derive(Debug)]
pub enum NodeType {
    /// 行首标记
    Main,
    /// 开始语句 ({)
    Starter,
    /// 可执行语法节点
    Executor(Executor),
    /// 结束语句 (})
    End,
    /// 注释
    Comment,
    /// 空行
    Blank,
    /// 未知代码
    Unknown,
}

impl From<&String> for Node {
    fn from(code: &String) -> Self {
        Self::from(code.as_str())
    }
}

impl From<&str> for Node {
    fn from(code: &str) -> Self {
        let exe = Executor::from(code);
        if code.len() == 0 || code.is_empty() {
            Node::new(code, NodeType::Blank)
        } else if code.starts_with("{") {
            Node::new(code, NodeType::Starter)
        } else if code.starts_with("}") {
            Node::new(code, NodeType::End)
        } else if code.starts_with("//") {
            Node::new(code, NodeType::Comment)
        } else if code.contains("@Main") {
            Node::new(code, NodeType::Main)
        } else if false == exe.caller.eq(Executor::default().caller.as_str()) {
            Node::new(code, NodeType::Executor(exe))
        } else {
            Node::default()
        }
    }
}

impl NodeType {
    /// 节点枚举分类，配置行数
    pub fn classify(code: &String, line: usize) -> Node {
        Node::from(code).line(line)
    }
}

/// 函数参数类型
#[derive(Debug, Clone)]
pub enum Param {
    /// 执行主体
    Caller(String),
    /// 静态字符串
    Static(String),
    /// 变量
    Var(String),
    /// 数值类型
    Number(String),
    /// 无法解析
    Unknown(String),
}

impl From<&str> for Param {
    fn from(param: &str) -> Self {
        Self::from(param.to_string())
    }
}

impl From<&String> for Param {
    fn from(param: &String) -> Self {
        Self::from(param.to_string())
    }
}

impl From<&crate::Value> for Param {
    fn from(v: &crate::Value) -> Self {
        Self::from(v.display())
    }
}

impl From<crate::Value> for Param {
    fn from(v: crate::Value) -> Self {
        Self::from(v.display())
    }
}

impl From<String> for Param {
    fn from(param: String) -> Self {
        let param = param.trim().to_string();
        if param.starts_with("\"") && param.ends_with("\"") {
            Param::Static(param[1..param.len() - 1].to_string())
        } else if param.starts_with("$") && !param.ends_with("\"") {
            Param::Var(param)
        } else if !param.starts_with("$")
            && !param.starts_with("\"")
            && !param.ends_with("\"")
            && param.parse::<f64>().is_ok()
        {
            Param::Number(param)
        } else {
            Param::Unknown(param)
        }
    }
}

/// 可执行语法节点
#[derive(Debug, Clone)]
pub struct Executor {
    /// 执行主体
    pub caller: String,
    /// 函数参数
    pub params: Vec<Param>,
}

impl Executor {
    pub fn new<S: Into<String>>(caller: S, params: Vec<Param>) -> Self {
        Self {
            caller: caller.into(),
            params,
        }
    }
}

impl Default for Executor {
    fn default() -> Self {
        Self::new("?Unknown", vec![])
    }
}

impl From<&str> for Executor {
    fn from(code: &str) -> Self {
        code.find('(')
            .map(|i| {
                Self::new(
                    &code[..i],
                    code[i + 1..code.len() - 1]
                        .split(")(")
                        .map(Into::into)
                        .collect(),
                )
            })
            .unwrap_or_default()
    }
}
